package td.pt.widget;

import td.client.ClientState;
import td.client.ui.Button;
import td.domain.DemoStore;
import td.domain.TagDef;
import td.domain.Thought;
import td.domain.util.StatisticalComparison;
import td.pt.event.ThoughtListingEvent;
import td.pt.event.TagAThoughtEvent;
import td.pt.event.UseTagNavigationEvent;
import td.pt.event.UseTagNavigationEvent.UseTagNavigationHandler;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellBrowser;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.PopupView;
import com.gwtplatform.mvp.client.PresenterWidget;
import com.gwtplatform.mvp.client.proxy.RevealRootPopupContentEvent;

public class TagTreePopupPresenter extends
		PresenterWidget<TagTreePopupPresenter.MyView> {

	public enum TagNavigationType {
		SELECT_TAGGED_BY_THOUGHTS, TAG_THOUGHT;
	}

	public interface MyView extends PopupView {
		Button getSelectTag();

		Button getTagThought();

		Button getCancel();

		CellBrowser getTagBrowser();

		SingleSelectionModel<TagDef> getSelectionModel();

		Label getBrowserPurposeDescription();

		public RadioButton getOrderAlphabetic();

		public RadioButton getOrderNumberOfThoughts();

		public RadioButton getOrderNumberOfReads();

		public void refresh();
	}

	UseTagNavigationHandler useTagNavigationHandler = new UseTagNavigationHandler() {

		@Override
		public void onUseTagNavigation(UseTagNavigationEvent event) {
			String subHeaderText = "";
			switch (event.getNavigationType()) {
			case TAG_THOUGHT:
				subHeaderText = "Select a Tag to be added to this Thought";
				getView().getTagThought().setVisible(true);
				getView().getSelectTag().setVisible(false);
				break;
			case SELECT_TAGGED_BY_THOUGHTS:
				subHeaderText = "Select a Tag to display Thoughts that are tagged with it.";
				getView().getTagThought().setVisible(false);
				getView().getSelectTag().setVisible(true);
				break;
			}
			getView().getBrowserPurposeDescription().setText(subHeaderText);
			RevealRootPopupContentEvent.fire(event.getSource(),
					TagTreePopupPresenter.this);
		}
	};

	@Inject
	ClientState state;

	@Inject
	public TagTreePopupPresenter(final EventBus eventBus, final MyView view) {
		super(eventBus, view);
	}

	@Override
	protected void onBind() {
		super.onBind();
		registerHandler(getEventBus().addHandler(UseTagNavigationEvent.TYPE,
				useTagNavigationHandler));
		getView().getSelectTag().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				TagDef tag = getView().getSelectionModel().getSelectedObject();
				if (tag == null) {
					return;
				}
				ThoughtListingEvent<TagDef> newTagListingEvent = new ThoughtListingEvent<TagDef>(
						"Top Thoughts for the " + tag.getName() + " tag", tag);
				getEventBus().fireEvent(newTagListingEvent);
				getView().hide();
			}
		});
		getView().getTagThought().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				TagDef tagDef = getView().getSelectionModel()
						.getSelectedObject();
				if (tagDef == null) {
					return;
				}
				Thought thoughtToTag = state.getCurrentThought();
				if (thoughtToTag.getThinker().getId()
						.equals(state.getThinker().getId())) {
					Window.alert("Cannot tag your own thought");
					return;

				}

				if (!DemoStore.db().canAddTagToThought(state.getThinker(),
						thoughtToTag, tagDef)) {
					Window.alert("You have allready tagged this thought with '"
							+ tagDef.getName() + "'");
				}
				DemoStore.db().addTag(thoughtToTag, tagDef, state.getThinker());

				TagAThoughtEvent tagAThoughtEvent = new TagAThoughtEvent(
						tagDef, TagTreePopupPresenter.this);
				getEventBus().fireEvent(tagAThoughtEvent);
				getView().hide();
			}
		});
		getView().getCancel().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				getView().hide();
			}
		});

		getView().getOrderAlphabetic().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				refresh(StatisticalComparison.ALPHABETIC);
			}
		});
		getView().getOrderNumberOfReads().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				refresh(StatisticalComparison.NUMBER_OF_THOUGHT_READS);
			}
		});
		getView().getOrderNumberOfThoughts().addClickHandler(
				new ClickHandler() {
					@Override
					public void onClick(ClickEvent event) {
						refresh(StatisticalComparison.NUMBER_OF_THOUGHTS);
					}
				});
	}

	private void refresh(StatisticalComparison comparisonType) {
		TagDef.currentComparisonType = comparisonType;
		DemoStore.db().reorder(DemoStore.db().rootTag);
		getView().refresh();
	}

	@Override
	protected void onReveal() {
		super.onReveal();

		switch (TagDef.currentComparisonType) {
		case ALPHABETIC:
			getView().getOrderAlphabetic().setValue(true);
			break;
		case NUMBER_OF_THOUGHT_READS:
			getView().getOrderNumberOfReads().setValue(true);
			break;
		case NUMBER_OF_THOUGHTS:
			getView().getOrderNumberOfThoughts().setValue(true);
			break;
		default:
			throw new RuntimeException(
					"Other comparison types are not yet supported.");
		}
	}
}
